﻿#region << 版 本 注 释 >>
/*----------------------------------------------------------------
 * 版权所有 (c) 2022 北京超维景生物科技有限公司 保留所有权利。
 * 
 * 创建者：huangyang
 * 电子邮箱：huangyang@tvscope.cn
 * 创建时间：2023/2/16 10:22:31
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion << 版 本 注 释 >>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ImageK.Measure;

namespace ImageK.Process
{
	/// <summary>
	/// 16-bit image statistics, including histogram.
	/// </summary>
	public class ShortStatistics: ImageStatistics
	{
		/** Construct an ImageStatistics object from a ShortProcessor
	    using the standard measurement options (area, mean,
	    mode, min and max). */
		public ShortStatistics(ImageProcessor ip): this(ip, AREA + MEAN + MODE + MIN_MAX, null)
		{
            
		}

		/** Constructs a ShortStatistics object from a ShortProcessor using
			the specified measurement options. The 'cal' argument, which
			can be null, is currently ignored. */
		public ShortStatistics(ImageProcessor ip, int mOptions, Calibration cal)
		{
			this.width = ip.getWidth();
			this.height = ip.getHeight();
			setup(ip, cal);
			nBins = 256;
			double minT = ip.getMinThreshold();
			int minThreshold, maxThreshold;
			bool limitToThreshold = (mOptions & LIMIT) != 0;
			if (!limitToThreshold || minT == ImageProcessor.NO_THRESHOLD)
			{
				minThreshold = 0;
				maxThreshold = 65535;
			}
			else
			{
				minThreshold = (int)minT;
				maxThreshold = (int)ip.getMaxThreshold();
			}
			if (limitToThreshold)
				saveThreshold(minThreshold, maxThreshold, cal);
			Rectangle r = ip.getRoi();
			bool smallRoi = r.Width * r.Height < 250000;
			int[] hist = smallRoi && (ip is ShortProcessor)?((ShortProcessor)ip).getHistogram2():ip.getHistogram();
			if (maxThreshold > hist.Length - 1)
				maxThreshold = hist.Length - 1;
			histogram16 = hist;
			float[] cTable = cal != null ? cal.getCTable() : null;
			getRawMinAndMax(hist, minThreshold, maxThreshold);
			histMin = min;
			histMax = max;
			getStatistics(ip, hist, (int)min, (int)max, cTable);

			//todo:
			// if ((mOptions & MODE) != 0)
			// 	getMode();
			// if ((mOptions & ELLIPSE) != 0 || (mOptions & SHAPE_DESCRIPTORS) != 0)
			// 	fitEllipse(ip, mOptions);
			// else if ((mOptions & CENTROID) != 0)
			// 	getCentroid(ip, minThreshold, maxThreshold);
			// if ((mOptions & (CENTER_OF_MASS | SKEWNESS | KURTOSIS)) != 0)
			// 	calculateMoments(ip, minThreshold, maxThreshold, cTable);
			// if ((mOptions & MIN_MAX) != 0 && cTable != null)
			// 	getCalibratedMinAndMax(hist, (int)min, (int)max, cTable);
			// if ((mOptions & MEDIAN) != 0)
			// {
			// 	if (pixelCount > 0)
			// 		calculateMedian(hist, minThreshold, maxThreshold, cal);
			// 	else
			// 		median = Double.NaN;
			// }
            if ((mOptions & AREA_FRACTION) != 0)
            {
                // calculateAreaFraction(ip, hist);
            }
				
		}

        void getRawMinAndMax(int[] hist, int minThreshold, int maxThreshold)
        {
            int min = minThreshold;
            if (min < hist.Length)
            {
                while ((hist[min] == 0) && (min < hist.Length - 1))
                    min++;
            }
            this.min = min;
            int max = maxThreshold;
            while ((hist[max] == 0) && (max > 0))
                max--;
            this.max = max;
        }

        void getStatistics(ImageProcessor ip, int[] hist, int min, int max, float[] cTable)
        {
            int count;
            double value;
            double sum = 0.0;
            double sum2 = 0.0;
            nBins = ip.getHistogramSize();
            histMin = ip.getHistogramMin();
            histMax = ip.getHistogramMax();
            if (histMin == 0.0 && histMax == 0.0)
            {
                histMin = min;
                histMax = max;
            }
            else
            {
                if (min < histMin) min = (int)histMin;
                if (max > histMax) max = (int)histMax;
            }
            binSize = (histMax - histMin) / nBins;
            double scale = 1.0 / binSize;
            int hMin = (int)histMin;
            Histogram = new int[nBins]; // 256 bin histogram
            int index;
            int maxCount = 0;

            for (int i = min; i <= max; i++)
            {
                count = hist[i];
                if (count > maxCount)
                {
                    maxCount = count;
                    dmode = i;
                }
                pixelCount += count;
                value = cTable == null ? i : cTable[i];
                sum += value * count;
                sum2 += (value * value) * count;
                index = (int)(scale * (i - hMin));
                if (index >= nBins)
                    index = nBins - 1;
                Histogram[index] += count;
            }
            area = pixelCount * pw * ph;
            mean = sum / pixelCount;
            umean = mean;
            calculateStdDev(pixelCount, sum, sum2);
            if (cTable != null)
                dmode = cTable[(int)dmode];
        }

	}
}
